﻿using System.Data.Common;

namespace Swimj.DataCore;

public class SqlServerDatabaseProvider : DatabaseProvider
{
    public override DbProviderFactory GetFactory()
    {
        return GetFactory(
            "System.Data.SqlClient.SqlClientFactory, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
    }

    public override string BuildPageQuery(long skip, long take, SqlParts parts)
    {
        var helper = (PagingHelper)PagingUtility;
        // when the query does not contain an "order by", it is very slow
        if (helper.SimpleRegexOrderBy.IsMatch(parts.SqlSelectRemoved))
        {
            var m = helper.SimpleRegexOrderBy.Match(parts.SqlSelectRemoved);
            if (m.Success)
            {
                var g = m.Groups[0];
                parts.SqlSelectRemoved = parts.SqlSelectRemoved.Substring(0, g.Index);
            }
        }

        if (helper.RegexDistinct.IsMatch(parts.SqlSelectRemoved))
        {
            parts.SqlSelectRemoved = "peta_inner.* FROM (SELECT " + parts.SqlSelectRemoved + ") peta_inner";
        }

        var sqlPage =
            $"SELECT * FROM (SELECT ROW_NUMBER() OVER ({parts.SqlOrderBy ?? "ORDER BY (SELECT NULL)"}) peta_rn, {parts.SqlSelectRemoved}) peta_paged WHERE peta_rn > {skip} AND peta_rn <= {skip + take}";
        return sqlPage;
    }

    public override string GetExistsSql()
    {
        return "IF EXISTS (SELECT 1 FROM {0} WHERE {1}) SELECT 1 ELSE SELECT 0";
    }

    public override string GetInsertOutputClause(string primaryKeyName)
    {
        return $" OUTPUT INSERTED.[{primaryKeyName}]";
    }
}